/**
 * Copyright 2002 Cordys R&D B.V. 
 * 
 * This file is part of the Cordys .NET Connector. 
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.eibus.applicationconnector.dotnet;

import com.eibus.applicationconnector.dotnet.localization.message.Messages;
import com.eibus.soap.ApplicationTransaction;
import com.eibus.soap.BodyBlock;
import com.eibus.soap.fault.Fault;
import com.eibus.soap.fault.FaultDetail;
import com.eibus.xml.nom.Node;
import com.eibus.xml.xpath.XPath;
import com.eibus.xml.xpath.XPathMetaInfo;
import com.eibus.util.CordysConstants;
import com.eibus.util.logger.CordysLogger;


/**
  *  Transaction.java , used to delegate the call to the .NET
  *			Release all the resources on stop of the application connector.
  *
  */
class Transaction  implements ApplicationTransaction
{

	static CordysLogger dotnetLogger = CordysLogger.getCordysLogger(Transaction.class);
    
    /* XPath for SOAP Fault */
    private static final XPath soapFaultXPath = new XPath("descendant-or-self::" +CordysConstants.CORDYS_DEFAULT_SOAP_PREFIX+ ":Fault");
    private static final XPathMetaInfo soapFaultMeta  = new XPathMetaInfo();
    
    static
    {
        soapFaultMeta.addNamespaceBinding(CordysConstants.CORDYS_DEFAULT_SOAP_PREFIX, CordysConstants.SOAP11_ENVELOPE_NAMESPACE);
    }
	
	public void commit()
	{
	}

	public void abort()
	{
	}

	public boolean canProcess(String type)
	{
		return "DotnetCall".equals(type);
	}


	private  native boolean Invoke(int request, int response,int implementation);  //NOPMD - this is a native method name


   /*
	*	Reads the request,response ,implemenation and then
	* 		pass these values directly to the jnet.dll by making call to Invoke
	*		method of jnet.dll.
	*
	*   All the  operations are implemented in jnet.dll, including soap fault handling.
	*
	*	jnet.dll reads the request , implementation Node pointers and invokes .NET methods.
	*		set the result to the response Node ponter
	*
	*/
	public boolean process(BodyBlock request, BodyBlock response)
	{

		boolean invoked =false;
		try
		{

			int responseNode 	= response.getXMLNode();
			int requestNode	 	= request.getXMLNode();
			int implementation  = request.getMethodDefinition().getImplementation();
			
			if (dotnetLogger.isInfoEnabled())
				dotnetLogger.info("Request received to the .NETCall Service is ..\n" +Node.writeToString(requestNode,true));
			
			invoked 			= Invoke(requestNode,responseNode,implementation);
			if (invoked == false)
			{
				//	returning response with out creating SoapFault , only
				//      in the case of dependency error
				//
				//  ie, If xmlForDotnet.dll  is not in the GAC OR
				//			any dependendant dll's for xmlForDotnet is missing
				//
				//if (Find.firstMatch(responseNode,"?<SOAP:Fault>") == 0)   // NOM to XPath
                if(soapFaultXPath.firstMatch(responseNode, soapFaultMeta) == 0)
				{
					if (dotnetLogger.isErrorEnabled())
						dotnetLogger.error("A .NET Connector dependant file or assembly was not found in " +
                                "the Path /Global Assembly Cache. Verify if xmlForDotnet.dll is registered in the GAC.");
					
					Fault fault = response.createSOAPFault(Fault.Codes.SERVER,Messages.FILE_NOT_FOUND);
					FaultDetail faultDetail = fault.getDetail();
				}
			}
		    if (dotnetLogger.isInfoEnabled())
			  dotnetLogger.info("Response from .NETCall Service is ..\n"+Node.writeToString(responseNode,true));
		}
		catch(Exception ex)
		{
			//	creating Document only in the case Exception at the java Layer
			//  All the .NET Exceptions are handled in jnet.dll
			
			if (dotnetLogger.isErrorEnabled())
				dotnetLogger.error(".NET Native Exception  : Failed to invoke the Method",ex);
			Fault fault = response.createSOAPFault(Fault.Codes.SERVER,Messages.NATIVE_EXCEPTION);
			FaultDetail faultDetail = fault.getDetail();			
			faultDetail.addDetailEntry(ex);			
			
		}
		
		return invoked;
	}

}
